{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "mat1 and mat2 shapes cannot be multiplied (10x20 and 10x500)\nCause: @ on tensor operand W w/shape [10, 20] and operand X.T w/shape [10, 500]",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "\u001b[0;32m/var/folders/93/9kzk2ccm8xj8k70059b28jk80000gp/T/ipykernel_55352/3024069779.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0mX\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrand\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m500\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mtsensor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexplain\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msavefig\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'/tmp/mm.pdf'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m     \u001b[0mY\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mW\u001b[0m \u001b[0;34m@\u001b[0m \u001b[0mX\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mT\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mRuntimeError\u001b[0m: mat1 and mat2 shapes cannot be multiplied (10x20 and 10x500)\nCause: @ on tensor operand W w/shape [10, 20] and operand X.T w/shape [10, 500]"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import tsensor\n",
    "W = torch.rand(10,20)\n",
    "b = torch.rand(10,1)\n",
    "X = torch.rand(500,10)\n",
    "with tsensor.explain(savefig='/tmp/mm.svg'):\n",
    "    Y = W @ X.T + b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" height=\"52.941034pt\" version=\"1.1\" viewBox=\"0 0 310.923169 52.941034\" width=\"310.923169pt\">\n",
       " <metadata>\n",
       "  <rdf:RDF xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
       "   <cc:Work>\n",
       "    <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
       "    <dc:date>2021-12-11T13:06:18.685523</dc:date>\n",
       "    <dc:format>image/svg+xml</dc:format>\n",
       "    <dc:creator>\n",
       "     <cc:Agent>\n",
       "      <dc:title>Matplotlib v3.3.4, https://matplotlib.org/</dc:title>\n",
       "     </cc:Agent>\n",
       "    </dc:creator>\n",
       "   </cc:Work>\n",
       "  </rdf:RDF>\n",
       " </metadata>\n",
       " <defs>\n",
       "  <style type=\"text/css\">*{stroke-linecap:butt;stroke-linejoin:round;}</style>\n",
       " </defs>\n",
       " <g id=\"figure_1\">\n",
       "  <g id=\"patch_1\">\n",
       "   <path d=\"M 0 52.941034  L 310.923169 52.941034  L 310.923169 0  L 0 0  z \" style=\"fill:none;\"/>\n",
       "  </g>\n",
       "  <g id=\"axes_1\">\n",
       "   <g id=\"patch_2\">\n",
       "    <path clip-path=\"url(#pf8405f6392)\" d=\"M 109.57446 45.180316  L 114.79734 45.180316  L 114.79734 22.919896  L 109.57446 22.919896  z \" style=\"fill:#7fa4d3;fill-opacity:0.75;stroke:#808080;stroke-linejoin:miter;stroke-width:0.7;\"/>\n",
       "   </g>\n",
       "   <g id=\"patch_3\">\n",
       "    <path clip-path=\"url(#pf8405f6392)\" d=\"M 143.72406 45.180316  L 148.94694 45.180316  L 148.94694 22.919896  L 143.72406 22.919896  z \" style=\"fill:#7fa4d3;fill-opacity:0.75;stroke:#808080;stroke-linejoin:miter;stroke-width:0.7;\"/>\n",
       "   </g>\n",
       "   <g id=\"line2d_1\">\n",
       "    <path clip-path=\"url(#pf8405f6392)\" d=\"M 108.26874 13.192653  L 116.10306 13.192653  \" style=\"fill:none;stroke:#c2c2c2;stroke-linecap:square;stroke-width:0.5;\"/>\n",
       "   </g>\n",
       "   <g id=\"line2d_2\">\n",
       "    <path clip-path=\"url(#pf8405f6392)\" d=\"M 142.41834 13.192653  L 150.25266 13.192653  \" style=\"fill:none;stroke:#c2c2c2;stroke-linecap:square;stroke-width:0.5;\"/>\n",
       "   </g>\n",
       "   <g id=\"text_1\">\n",
       "    <!-- W -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(6.975 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 52.78125 63.8125  L 48.484375 0  L 37.203125 0  L 29.296875 22.703125  L 27.09375 29.984375  L 24.8125 22.125  L 17.484375 0  L 6.59375 0  L 2.203125 63.8125  L 10.40625 63.8125  L 12.890625 20.40625  L 13.625 8.5  L 16.703125 18.609375  L 24.421875 42.28125  L 30.421875 42.28125  L 39.3125 16.890625  L 42.28125 8.5  L 42.484375 17.28125  L 45.015625 63.8125  z \" id=\"Consolas-87\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-87\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_2\">\n",
       "    <!--   -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(13.5036 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path id=\"Consolas-32\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-32\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_3\">\n",
       "    <!-- @ -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(20.0322 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 38.09375 19.921875  Q 37.640625 16.796875 37.59375 14.75  Q 37.546875 12.703125 37.859375 11.53125  Q 38.1875 10.359375 38.859375 9.890625  Q 39.546875 9.421875 40.578125 9.421875  Q 41.9375 9.421875 43.15625 10.859375  Q 44.390625 12.3125 45.34375 15.3125  Q 46.296875 18.3125 46.84375 22.890625  Q 47.40625 27.484375 47.40625 33.796875  Q 47.40625 40.828125 46.53125 46.34375  Q 45.65625 51.859375 43.75 55.71875  Q 41.84375 59.578125 38.796875 61.59375  Q 35.75 63.625 31.390625 63.625  Q 28.078125 63.625 24.96875 61.9375  Q 21.875 60.25 19.203125 57.203125  Q 16.546875 54.15625 14.375 49.875  Q 12.203125 45.609375 10.65625 40.421875  Q 9.125 35.25 8.265625 29.296875  Q 7.421875 23.34375 7.421875 16.890625  Q 7.421875 1.171875 12.15625 -6.5625  Q 16.890625 -14.3125 25.484375 -14.3125  Q 29.828125 -14.3125 33.59375 -13.3125  Q 37.359375 -12.3125 41.40625 -10.296875  L 41.40625 -16.609375  Q 37.40625 -18.453125 33.390625 -19.375  Q 29.390625 -20.3125 25 -20.3125  Q 12.546875 -20.3125 6.5625 -10.984375  Q 0.59375 -1.65625 0.484375 16.796875  Q 0.4375 24.171875 1.453125 30.9375  Q 2.484375 37.703125 4.40625 43.5625  Q 6.34375 49.421875 9.09375 54.21875  Q 11.859375 59.03125 15.34375 62.421875  Q 18.84375 65.828125 22.9375 67.703125  Q 27.046875 69.578125 31.6875 69.578125  Q 37.5 69.578125 41.765625 67.203125  Q 46.046875 64.84375 48.828125 60.375  Q 51.609375 55.90625 52.953125 49.40625  Q 54.296875 42.921875 54.296875 34.625  Q 54.25 26.21875 53.203125 20.234375  Q 52.15625 14.265625 50.25 10.453125  Q 48.34375 6.640625 45.625 4.859375  Q 42.921875 3.078125 39.59375 3.078125  Q 35.796875 3.078125 33.9375 5.03125  Q 32.078125 6.984375 32.078125 10.296875  Q 30.21875 6.546875 28.0625 4.8125  Q 25.921875 3.078125 22.90625 3.078125  Q 18.3125 3.078125 16.015625 6.515625  Q 13.71875 9.96875 13.71875 17.390625  Q 13.71875 20.0625 14.03125 23.140625  Q 14.359375 26.21875 15.109375 29.3125  Q 15.875 32.421875 17.09375 35.28125  Q 18.3125 38.140625 20.09375 40.3125  Q 21.875 42.484375 24.3125 43.796875  Q 26.765625 45.125 29.890625 45.125  Q 31.734375 45.125 33.34375 44.671875  Q 34.96875 44.234375 35.6875 43.796875  L 42 45.3125  z M 33.109375 37.3125  Q 32.671875 37.890625 31.765625 38.34375  Q 30.859375 38.8125 29.5 38.8125  Q 28.03125 38.8125 26.859375 37.78125  Q 25.6875 36.765625 24.78125 35.046875  Q 23.875 33.34375 23.265625 31.171875  Q 22.65625 29 22.234375 26.703125  Q 21.828125 24.421875 21.65625 22.1875  Q 21.484375 19.96875 21.484375 18.21875  Q 21.484375 13.53125 22.0625 11.46875  Q 22.65625 9.421875 24.3125 9.421875  Q 24.90625 9.421875 25.484375 9.65625  Q 26.078125 9.90625 26.734375 10.609375  Q 27.390625 11.328125 28.171875 12.59375  Q 28.953125 13.875 29.890625 15.921875  z \" id=\"Consolas-64\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-64\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_4\">\n",
       "    <!--   -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(26.5608 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-32\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_5\">\n",
       "    <!-- t -->\n",
       "    <g style=\"fill:#444443;\" transform=\"translate(33.0894 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 47.3125 0.6875  Q 44.4375 -0.046875 41.359375 -0.359375  Q 38.28125 -0.6875 35.109375 -0.6875  Q 25.875 -0.6875 21.328125 3.484375  Q 16.796875 7.671875 16.796875 16.3125  L 16.796875 41.890625  L 3.078125 41.890625  L 3.078125 49.03125  L 16.796875 49.03125  L 16.796875 62.5  L 25.296875 64.703125  L 25.296875 49.03125  L 47.3125 49.03125  L 47.3125 41.890625  L 25.296875 41.890625  L 25.296875 17  Q 25.296875 11.71875 28.09375 9.109375  Q 30.90625 6.5 36.375 6.5  Q 38.71875 6.5 41.5 6.859375  Q 44.28125 7.234375 47.3125 8.015625  z \" id=\"Consolas-116\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-116\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_6\">\n",
       "    <!-- o -->\n",
       "    <g style=\"fill:#444443;\" transform=\"translate(39.618 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 50.484375 24.90625  Q 50.484375 19.1875 48.875 14.421875  Q 47.265625 9.671875 44.234375 6.265625  Q 41.21875 2.875 36.859375 1  Q 32.515625 -0.875 27 -0.875  Q 21.734375 -0.875 17.546875 0.75  Q 13.375 2.390625 10.46875 5.5625  Q 7.5625 8.734375 6.03125 13.421875  Q 4.5 18.109375 4.5 24.21875  Q 4.5 29.9375 6.109375 34.640625  Q 7.71875 39.359375 10.734375 42.75  Q 13.765625 46.140625 18.109375 48.015625  Q 22.46875 49.90625 27.984375 49.90625  Q 33.25 49.90625 37.421875 48.265625  Q 41.609375 46.625 44.5 43.46875  Q 47.40625 40.328125 48.9375 35.640625  Q 50.484375 30.953125 50.484375 24.90625  z M 41.796875 24.515625  Q 41.796875 29.046875 40.796875 32.4375  Q 39.796875 35.84375 37.9375 38.109375  Q 36.078125 40.375 33.421875 41.515625  Q 30.765625 42.671875 27.484375 42.671875  Q 23.6875 42.671875 20.96875 41.1875  Q 18.265625 39.703125 16.53125 37.203125  Q 14.796875 34.71875 13.984375 31.421875  Q 13.1875 28.125 13.1875 24.515625  Q 13.1875 19.96875 14.1875 16.546875  Q 15.1875 13.140625 17.03125 10.859375  Q 18.890625 8.59375 21.53125 7.4375  Q 24.171875 6.296875 27.484375 6.296875  Q 31.296875 6.296875 34 7.78125  Q 36.71875 9.28125 38.453125 11.765625  Q 40.1875 14.265625 40.984375 17.546875  Q 41.796875 20.84375 41.796875 24.515625  z \" id=\"Consolas-111\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-111\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_7\">\n",
       "    <!-- r -->\n",
       "    <g style=\"fill:#444443;\" transform=\"translate(46.1466 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 9.8125 49.03125  L 17.578125 49.03125  L 17.828125 39.984375  Q 22.171875 45.21875 26.390625 47.5625  Q 30.609375 49.90625 34.90625 49.90625  Q 42.53125 49.90625 46.453125 44.96875  Q 50.390625 40.046875 50.09375 30.328125  L 41.5 30.328125  Q 41.65625 36.765625 39.625 39.671875  Q 37.59375 42.578125 33.6875 42.578125  Q 31.984375 42.578125 30.25 41.96875  Q 28.515625 41.359375 26.6875 40.015625  Q 24.859375 38.671875 22.796875 36.5625  Q 20.75 34.46875 18.40625 31.5  L 18.40625 0  L 9.8125 0  z \" id=\"Consolas-114\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-114\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_8\">\n",
       "    <!-- c -->\n",
       "    <g style=\"fill:#444443;\" transform=\"translate(52.6752 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 45.90625 1.8125  Q 42.578125 0.53125 39.078125 -0.078125  Q 35.59375 -0.6875 31.890625 -0.6875  Q 20.265625 -0.6875 13.984375 5.609375  Q 7.71875 11.921875 7.71875 24.03125  Q 7.71875 29.828125 9.515625 34.5625  Q 11.328125 39.3125 14.59375 42.671875  Q 17.875 46.046875 22.40625 47.875  Q 26.953125 49.703125 32.421875 49.703125  Q 36.234375 49.703125 39.546875 49.171875  Q 42.875 48.640625 45.90625 47.40625  L 45.90625 39.3125  Q 42.71875 40.96875 39.421875 41.71875  Q 36.140625 42.484375 32.625 42.484375  Q 29.34375 42.484375 26.4375 41.234375  Q 23.53125 39.984375 21.328125 37.640625  Q 19.140625 35.296875 17.875 31.921875  Q 16.609375 28.5625 16.609375 24.3125  Q 16.609375 15.4375 20.921875 11.015625  Q 25.25 6.59375 32.90625 6.59375  Q 36.375 6.59375 39.625 7.375  Q 42.875 8.15625 45.90625 9.71875  z \" id=\"Consolas-99\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-99\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_9\">\n",
       "    <!-- h -->\n",
       "    <g style=\"fill:#444443;\" transform=\"translate(59.2038 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 47.21875 0  L 38.71875 0  L 38.71875 31.296875  Q 38.71875 36.96875 36.59375 39.765625  Q 34.46875 42.578125 30.515625 42.578125  Q 28.8125 42.578125 27.3125 42.109375  Q 25.828125 41.65625 24.21875 40.5  Q 22.609375 39.359375 20.703125 37.40625  Q 18.796875 35.453125 16.3125 32.515625  L 16.3125 0  L 7.8125 0  L 7.8125 69  L 16.3125 69  L 16.3125 49.03125  L 16.015625 41.3125  Q 18.015625 43.703125 19.9375 45.328125  Q 21.875 46.96875 23.796875 48  Q 25.734375 49.03125 27.734375 49.46875  Q 29.734375 49.90625 31.890625 49.90625  Q 39.203125 49.90625 43.203125 45.4375  Q 47.21875 40.96875 47.21875 31.984375  z \" id=\"Consolas-104\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-104\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_10\">\n",
       "    <!-- . -->\n",
       "    <g style=\"fill:#444443;\" transform=\"translate(65.7324 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 27.09375 15.375  Q 28.765625 15.375 30.25 14.734375  Q 31.734375 14.109375 32.828125 12.984375  Q 33.9375 11.859375 34.5625 10.375  Q 35.203125 8.890625 35.203125 7.171875  Q 35.203125 5.515625 34.5625 4.046875  Q 33.9375 2.59375 32.828125 1.484375  Q 31.734375 0.390625 30.25 -0.234375  Q 28.765625 -0.875 27.09375 -0.875  Q 25.390625 -0.875 23.921875 -0.234375  Q 22.46875 0.390625 21.359375 1.484375  Q 20.265625 2.59375 19.625 4.046875  Q 19 5.515625 19 7.171875  Q 19 8.890625 19.625 10.375  Q 20.265625 11.859375 21.359375 12.984375  Q 22.46875 14.109375 23.921875 14.734375  Q 25.390625 15.375 27.09375 15.375  z \" id=\"Consolas-46\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-46\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_11\">\n",
       "    <!-- d -->\n",
       "    <g style=\"fill:#a40227;\" transform=\"translate(72.261 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 5.328125 23.484375  Q 5.328125 29.734375 7.03125 34.59375  Q 8.734375 39.453125 11.890625 42.796875  Q 15.046875 46.140625 19.453125 47.875  Q 23.875 49.609375 29.296875 49.609375  Q 31.640625 49.609375 33.90625 49.3125  Q 36.1875 49.03125 38.375 48.390625  L 38.375 69  L 46.921875 69  L 46.921875 0  L 39.3125 0  L 39.015625 9.28125  Q 35.453125 4.109375 31.296875 1.609375  Q 27.15625 -0.875 22.3125 -0.875  Q 18.109375 -0.875 14.90625 0.875  Q 11.71875 2.640625 9.59375 5.828125  Q 7.46875 9.03125 6.390625 13.515625  Q 5.328125 18.015625 5.328125 23.484375  z M 14.015625 24.03125  Q 14.015625 15.140625 16.625 10.765625  Q 19.234375 6.390625 24.03125 6.390625  Q 27.25 6.390625 30.828125 9.265625  Q 34.421875 12.15625 38.375 17.828125  L 38.375 40.578125  Q 36.28125 41.546875 33.734375 42.0625  Q 31.203125 42.578125 28.71875 42.578125  Q 21.78125 42.578125 17.890625 38.078125  Q 14.015625 33.59375 14.015625 24.03125  z \" id=\"Consolas-100\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-100\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_12\">\n",
       "    <!-- o -->\n",
       "    <g style=\"fill:#a40227;\" transform=\"translate(78.7896 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-111\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_13\">\n",
       "    <!-- t -->\n",
       "    <g style=\"fill:#a40227;\" transform=\"translate(85.3182 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-116\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_14\">\n",
       "    <!-- ( -->\n",
       "    <g style=\"fill:#a40227;\" transform=\"translate(91.8468 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 37.15625 -20.515625  Q 14.65625 0.34375 14.65625 25.59375  Q 14.65625 31.5 15.84375 37.375  Q 17.046875 43.265625 19.703125 49.171875  Q 22.359375 55.078125 26.734375 60.984375  Q 31.109375 66.890625 37.359375 72.703125  L 42.28125 67.671875  Q 23.34375 48.96875 23.34375 26.21875  Q 23.34375 14.890625 28.125 4.4375  Q 32.90625 -6 42.28125 -15.28125  z \" id=\"Consolas-40\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-40\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_15\">\n",
       "    <!-- b -->\n",
       "    <g style=\"fill:#444443;\" transform=\"translate(108.9216 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 49.703125 25.390625  Q 49.703125 19.28125 48.015625 14.46875  Q 46.34375 9.671875 43.234375 6.328125  Q 40.140625 2.984375 35.6875 1.1875  Q 31.25 -0.59375 25.6875 -0.59375  Q 21.34375 -0.59375 16.796875 0.234375  Q 12.25 1.078125 7.8125 2.875  L 7.8125 69  L 16.3125 69  L 16.3125 50  L 15.921875 40.921875  Q 19.578125 45.84375 23.75 47.875  Q 27.9375 49.90625 32.71875 49.90625  Q 36.921875 49.90625 40.09375 48.140625  Q 43.265625 46.390625 45.40625 43.1875  Q 47.5625 39.984375 48.625 35.46875  Q 49.703125 30.953125 49.703125 25.390625  z M 41.015625 25  Q 41.015625 28.859375 40.453125 32.078125  Q 39.890625 35.296875 38.671875 37.59375  Q 37.453125 39.890625 35.546875 41.1875  Q 33.640625 42.484375 31 42.484375  Q 29.390625 42.484375 27.734375 41.96875  Q 26.078125 41.453125 24.296875 40.25  Q 22.515625 39.0625 20.53125 37.078125  Q 18.5625 35.109375 16.3125 32.171875  L 16.3125 8.40625  Q 18.796875 7.421875 21.375 6.859375  Q 23.96875 6.296875 26.3125 6.296875  Q 29.25 6.296875 31.90625 7.21875  Q 34.578125 8.15625 36.59375 10.328125  Q 38.625 12.5 39.8125 16.078125  Q 41.015625 19.671875 41.015625 25  z \" id=\"Consolas-98\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-98\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_16\">\n",
       "    <!-- , -->\n",
       "    <g style=\"fill:#444443;\" transform=\"translate(125.9964 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 11.625 -10.015625  Q 14.109375 -10.109375 16.453125 -9.5625  Q 18.796875 -9.03125 20.578125 -7.984375  Q 22.359375 -6.9375 23.4375 -5.375  Q 24.515625 -3.8125 24.515625 -1.8125  Q 24.515625 0.25 23.796875 1.515625  Q 23.09375 2.78125 22.21875 3.859375  Q 21.34375 4.9375 20.625 6.15625  Q 19.921875 7.375 19.921875 9.421875  Q 19.921875 10.453125 20.3125 11.578125  Q 20.703125 12.703125 21.5 13.625  Q 22.3125 14.546875 23.5625 15.125  Q 24.8125 15.71875 26.515625 15.71875  Q 28.21875 15.71875 29.796875 15.015625  Q 31.390625 14.3125 32.59375 12.84375  Q 33.796875 11.375 34.5 9.171875  Q 35.203125 6.984375 35.203125 4  Q 35.203125 -0.046875 33.71875 -3.78125  Q 32.234375 -7.515625 29.265625 -10.390625  Q 26.3125 -13.28125 21.890625 -14.984375  Q 17.484375 -16.703125 11.625 -16.703125  z \" id=\"Consolas-44\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-44\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_17\">\n",
       "    <!-- b -->\n",
       "    <g style=\"fill:#444443;\" transform=\"translate(143.0712 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-98\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_18\">\n",
       "    <!-- ) -->\n",
       "    <g style=\"fill:#a40227;\" transform=\"translate(160.146 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 17.828125 72.703125  Q 40.328125 51.859375 40.328125 26.3125  Q 40.328125 21.046875 39.25 15.375  Q 38.1875 9.71875 35.59375 3.78125  Q 33.015625 -2.15625 28.640625 -8.25  Q 24.265625 -14.359375 17.625 -20.515625  L 12.703125 -15.484375  Q 22.21875 -6.0625 26.90625 4.1875  Q 31.59375 14.453125 31.59375 25.6875  Q 31.59375 48.921875 12.703125 67.484375  z \" id=\"Consolas-41\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-41\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_19\">\n",
       "    <!-- + -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(166.6746 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 50.875 22.90625  L 31.6875 22.90625  L 31.6875 2.984375  L 23.296875 2.984375  L 23.296875 22.90625  L 4.109375 22.90625  L 4.109375 30.328125  L 23.296875 30.328125  L 23.296875 50.09375  L 31.6875 50.09375  L 31.6875 30.328125  L 50.875 30.328125  z \" id=\"Consolas-43\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-43\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_20\">\n",
       "    <!--   -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(173.2032 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-32\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_21\">\n",
       "    <!-- t -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(179.7318 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-116\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_22\">\n",
       "    <!-- o -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(186.2604 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-111\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_23\">\n",
       "    <!-- r -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(192.789 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-114\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_24\">\n",
       "    <!-- c -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(199.3176 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-99\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_25\">\n",
       "    <!-- h -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(205.8462 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-104\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_26\">\n",
       "    <!-- . -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(212.3748 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-46\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_27\">\n",
       "    <!-- e -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(218.9034 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 49.21875 27.09375  Q 49.21875 25.296875 49.171875 24.078125  Q 49.125 22.859375 49.03125 21.78125  L 14.59375 21.78125  Q 14.59375 14.265625 18.796875 10.234375  Q 23 6.203125 30.90625 6.203125  Q 33.0625 6.203125 35.203125 6.375  Q 37.359375 6.546875 39.359375 6.828125  Q 41.359375 7.125 43.1875 7.484375  Q 45.015625 7.859375 46.578125 8.296875  L 46.578125 1.3125  Q 43.109375 0.34375 38.734375 -0.265625  Q 34.375 -0.875 29.6875 -0.875  Q 23.390625 -0.875 18.84375 0.828125  Q 14.3125 2.546875 11.40625 5.78125  Q 8.5 9.03125 7.109375 13.734375  Q 5.71875 18.453125 5.71875 24.421875  Q 5.71875 29.59375 7.203125 34.203125  Q 8.6875 38.8125 11.546875 42.296875  Q 14.40625 45.796875 18.546875 47.84375  Q 22.703125 49.90625 27.984375 49.90625  Q 33.109375 49.90625 37.0625 48.296875  Q 41.015625 46.6875 43.71875 43.71875  Q 46.4375 40.765625 47.828125 36.546875  Q 49.21875 32.328125 49.21875 27.09375  z M 40.375 28.328125  Q 40.53125 31.59375 39.75 34.296875  Q 38.96875 37.015625 37.328125 38.96875  Q 35.6875 40.921875 33.25 42.015625  Q 30.8125 43.109375 27.59375 43.109375  Q 24.8125 43.109375 22.515625 42.03125  Q 20.21875 40.96875 18.546875 39.015625  Q 16.890625 37.0625 15.859375 34.328125  Q 14.84375 31.59375 14.59375 28.328125  z \" id=\"Consolas-101\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-101\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_28\">\n",
       "    <!-- y -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(225.432 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 51.421875 49.03125  L 34.71875 5.171875  Q 32.125 -1.515625 29.359375 -6.34375  Q 26.609375 -11.1875 23.328125 -14.28125  Q 20.0625 -17.390625 16.15625 -18.84375  Q 12.25 -20.3125 7.421875 -20.3125  Q 6.15625 -20.3125 5.125 -20.265625  Q 4.109375 -20.21875 2.875 -20.125  L 2.875 -12.40625  Q 3.953125 -12.546875 5.21875 -12.671875  Q 6.5 -12.796875 7.90625 -12.796875  Q 10.25 -12.796875 12.28125 -12.109375  Q 14.3125 -11.421875 16.109375 -9.875  Q 17.921875 -8.34375 19.578125 -5.90625  Q 21.234375 -3.46875 22.796875 0  L 3.21875 49.03125  L 12.890625 49.03125  L 25.296875 16.609375  L 27.78125 8.984375  L 30.609375 16.796875  L 42.09375 49.03125  z \" id=\"Consolas-121\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-121\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_29\">\n",
       "    <!-- e -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(231.9606 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-101\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_30\">\n",
       "    <!-- ( -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(238.4892 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-40\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_31\">\n",
       "    <!-- 2 -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(245.0178 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 49.21875 0  L 7.171875 0  L 7.171875 7.625  L 23.6875 24.03125  Q 27.734375 28.03125 30.265625 30.953125  Q 32.8125 33.890625 34.21875 36.296875  Q 35.640625 38.71875 36.125 40.859375  Q 36.625 43.015625 36.625 45.515625  Q 36.625 47.859375 35.984375 49.96875  Q 35.359375 52.09375 34.03125 53.703125  Q 32.71875 55.328125 30.609375 56.25  Q 28.515625 57.171875 25.59375 57.171875  Q 21.53125 57.171875 18.203125 55.359375  Q 14.890625 53.5625 12.109375 50.6875  L 7.421875 56.296875  Q 11.03125 60.109375 15.734375 62.40625  Q 20.453125 64.703125 26.703125 64.703125  Q 30.953125 64.703125 34.4375 63.421875  Q 37.9375 62.15625 40.46875 59.765625  Q 43.015625 57.375 44.40625 53.90625  Q 45.796875 50.4375 45.796875 46.09375  Q 45.796875 42.4375 44.8125 39.3125  Q 43.84375 36.1875 41.859375 33.078125  Q 39.890625 29.984375 36.890625 26.65625  Q 33.890625 23.34375 29.78125 19.390625  L 18.21875 8.109375  L 49.21875 8.109375  z \" id=\"Consolas-50\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-50\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_32\">\n",
       "    <!-- , -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(251.5464 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-44\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_33\">\n",
       "    <!-- 2 -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(258.075 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-50\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_34\">\n",
       "    <!-- ) -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(264.6036 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-41\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_35\">\n",
       "    <!-- @ -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(271.1322 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-64\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_36\">\n",
       "    <!-- x -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(277.6608 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 52 0  L 40.71875 0  L 27.484375 18.703125  L 14.40625 0  L 3.421875 0  L 22.40625 24.609375  L 4.296875 49.03125  L 15.1875 49.03125  L 28.078125 30.171875  L 40.71875 49.03125  L 51.21875 49.03125  L 32.8125 24.421875  z \" id=\"Consolas-120\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-120\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_37\">\n",
       "    <!--   -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(284.1894 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-32\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_38\">\n",
       "    <!-- + -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(290.718 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-43\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_39\">\n",
       "    <!--   -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(297.2466 9.451406)scale(0.13 -0.13)\">\n",
       "     <use xlink:href=\"#Consolas-32\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_40\">\n",
       "    <!-- z -->\n",
       "    <g style=\"fill:#b4b4b4;\" transform=\"translate(303.7752 9.451406)scale(0.13 -0.13)\">\n",
       "     <defs>\n",
       "      <path d=\"M 47.515625 0  L 8.015625 0  L 8.015625 6.109375  L 35.6875 41.890625  L 8.6875 41.890625  L 8.6875 49.03125  L 45.90625 49.03125  L 45.90625 42.390625  L 18.703125 7.171875  L 47.515625 7.171875  z \" id=\"Consolas-122\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#Consolas-122\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_41\">\n",
       "    <!-- 2 -->\n",
       "    <g transform=\"translate(107.78571 36.552528)rotate(-90)scale(0.09 -0.09)\">\n",
       "     <defs>\n",
       "      <path d=\"M 50.34375 8.453125  L 50.34375 0  L 3.03125 0  Q 2.9375 3.171875 4.046875 6.109375  Q 5.859375 10.9375 9.828125 15.625  Q 13.8125 20.3125 21.34375 26.46875  Q 33.015625 36.03125 37.109375 41.625  Q 41.21875 47.21875 41.21875 52.203125  Q 41.21875 57.421875 37.46875 61  Q 33.734375 64.59375 27.734375 64.59375  Q 21.390625 64.59375 17.578125 60.78125  Q 13.765625 56.984375 13.71875 50.25  L 4.6875 51.171875  Q 5.609375 61.28125 11.65625 66.578125  Q 17.71875 71.875 27.9375 71.875  Q 38.234375 71.875 44.234375 66.15625  Q 50.25 60.453125 50.25 52  Q 50.25 47.703125 48.484375 43.546875  Q 46.734375 39.40625 42.65625 34.8125  Q 38.578125 30.21875 29.109375 22.21875  Q 21.1875 15.578125 18.9375 13.203125  Q 16.703125 10.84375 15.234375 8.453125  z \" id=\"ArialMT-50\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#ArialMT-50\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_42\">\n",
       "    <!-- 1 -->\n",
       "    <g transform=\"translate(109.683478 21.560896)scale(0.09 -0.09)\">\n",
       "     <defs>\n",
       "      <path d=\"M 37.25 0  L 28.46875 0  L 28.46875 56  Q 25.296875 52.984375 20.140625 49.953125  Q 14.984375 46.921875 10.890625 45.40625  L 10.890625 53.90625  Q 18.265625 57.375 23.78125 62.296875  Q 29.296875 67.234375 31.59375 71.875  L 37.25 71.875  z \" id=\"ArialMT-49\"/>\n",
       "     </defs>\n",
       "     <use xlink:href=\"#ArialMT-49\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_43\">\n",
       "    <!-- &lt;${\\mathit{int64}}$&gt; -->\n",
       "    <g transform=\"translate(99.0609 51.549784)scale(0.07 -0.07)\">\n",
       "     <defs>\n",
       "      <path d=\"M 5.46875 31.296875  L 5.46875 39.5  L 52.875 59.515625  L 52.875 50.78125  L 15.28125 35.359375  L 52.875 19.78125  L 52.875 11.03125  z \" id=\"ArialMT-60\"/>\n",
       "      <path d=\"M 18.3125 75.984375  L 27.296875 75.984375  L 25.09375 64.59375  L 16.109375 64.59375  z M 14.203125 54.6875  L 23.1875 54.6875  L 12.5 0  L 3.515625 0  z \" id=\"DejaVuSans-Oblique-105\"/>\n",
       "      <path d=\"M 55.71875 33.015625  L 49.3125 0  L 40.28125 0  L 46.6875 32.671875  Q 47.125 34.96875 47.359375 36.71875  Q 47.609375 38.484375 47.609375 39.5  Q 47.609375 43.609375 45.015625 45.890625  Q 42.4375 48.1875 37.796875 48.1875  Q 30.5625 48.1875 25.34375 43.375  Q 20.125 38.578125 18.5 30.328125  L 12.5 0  L 3.515625 0  L 14.109375 54.6875  L 23.09375 54.6875  L 21.296875 46.09375  Q 25.046875 50.828125 30.3125 53.40625  Q 35.59375 56 41.40625 56  Q 48.640625 56 52.609375 52.09375  Q 56.59375 48.1875 56.59375 41.109375  Q 56.59375 39.359375 56.375 37.359375  Q 56.15625 35.359375 55.71875 33.015625  z \" id=\"DejaVuSans-Oblique-110\"/>\n",
       "      <path d=\"M 42.28125 54.6875  L 40.921875 47.703125  L 23 47.703125  L 17.1875 18.015625  Q 16.890625 16.359375 16.75 15.234375  Q 16.609375 14.109375 16.609375 13.484375  Q 16.609375 10.359375 18.484375 8.9375  Q 20.359375 7.515625 24.515625 7.515625  L 33.59375 7.515625  L 32.078125 0  L 23.484375 0  Q 15.484375 0 11.546875 3.125  Q 7.625 6.25 7.625 12.59375  Q 7.625 13.71875 7.765625 15.0625  Q 7.90625 16.40625 8.203125 18.015625  L 14.015625 47.703125  L 6.390625 47.703125  L 7.8125 54.6875  L 15.28125 54.6875  L 18.3125 70.21875  L 27.296875 70.21875  L 24.3125 54.6875  z \" id=\"DejaVuSans-Oblique-116\"/>\n",
       "      <path d=\"M 33.015625 40.375  Q 26.375 40.375 22.484375 35.828125  Q 18.609375 31.296875 18.609375 23.390625  Q 18.609375 15.53125 22.484375 10.953125  Q 26.375 6.390625 33.015625 6.390625  Q 39.65625 6.390625 43.53125 10.953125  Q 47.40625 15.53125 47.40625 23.390625  Q 47.40625 31.296875 43.53125 35.828125  Q 39.65625 40.375 33.015625 40.375  z M 52.59375 71.296875  L 52.59375 62.3125  Q 48.875 64.0625 45.09375 64.984375  Q 41.3125 65.921875 37.59375 65.921875  Q 27.828125 65.921875 22.671875 59.328125  Q 17.53125 52.734375 16.796875 39.40625  Q 19.671875 43.65625 24.015625 45.921875  Q 28.375 48.1875 33.59375 48.1875  Q 44.578125 48.1875 50.953125 41.515625  Q 57.328125 34.859375 57.328125 23.390625  Q 57.328125 12.15625 50.6875 5.359375  Q 44.046875 -1.421875 33.015625 -1.421875  Q 20.359375 -1.421875 13.671875 8.265625  Q 6.984375 17.96875 6.984375 36.375  Q 6.984375 53.65625 15.1875 63.9375  Q 23.390625 74.21875 37.203125 74.21875  Q 40.921875 74.21875 44.703125 73.484375  Q 48.484375 72.75 52.59375 71.296875  z \" id=\"DejaVuSans-54\"/>\n",
       "      <path d=\"M 37.796875 64.3125  L 12.890625 25.390625  L 37.796875 25.390625  z M 35.203125 72.90625  L 47.609375 72.90625  L 47.609375 25.390625  L 58.015625 25.390625  L 58.015625 17.1875  L 47.609375 17.1875  L 47.609375 0  L 37.796875 0  L 37.796875 17.1875  L 4.890625 17.1875  L 4.890625 26.703125  z \" id=\"DejaVuSans-52\"/>\n",
       "      <path d=\"M 52.875 31.296875  L 5.46875 11.03125  L 5.46875 19.78125  L 43.015625 35.359375  L 5.46875 50.78125  L 5.46875 59.515625  L 52.875 39.5  z \" id=\"ArialMT-62\"/>\n",
       "     </defs>\n",
       "     <use transform=\"translate(0 0.015625)\" xlink:href=\"#ArialMT-60\"/>\n",
       "     <use transform=\"translate(58.398438 0.015625)\" xlink:href=\"#DejaVuSans-Oblique-105\"/>\n",
       "     <use transform=\"translate(86.181641 0.015625)\" xlink:href=\"#DejaVuSans-Oblique-110\"/>\n",
       "     <use transform=\"translate(149.560547 0.015625)\" xlink:href=\"#DejaVuSans-Oblique-116\"/>\n",
       "     <use transform=\"translate(188.769531 0.015625)\" xlink:href=\"#DejaVuSans-54\"/>\n",
       "     <use transform=\"translate(252.392578 0.015625)\" xlink:href=\"#DejaVuSans-52\"/>\n",
       "     <use transform=\"translate(316.015625 0.015625)\" xlink:href=\"#ArialMT-62\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_44\">\n",
       "    <!-- 2 -->\n",
       "    <g transform=\"translate(141.93531 36.552528)rotate(-90)scale(0.09 -0.09)\">\n",
       "     <use xlink:href=\"#ArialMT-50\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_45\">\n",
       "    <!-- 1 -->\n",
       "    <g transform=\"translate(143.833078 21.560896)scale(0.09 -0.09)\">\n",
       "     <use xlink:href=\"#ArialMT-49\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"text_46\">\n",
       "    <!-- &lt;${\\mathit{int64}}$&gt; -->\n",
       "    <g transform=\"translate(133.2105 51.549784)scale(0.07 -0.07)\">\n",
       "     <use transform=\"translate(0 0.015625)\" xlink:href=\"#ArialMT-60\"/>\n",
       "     <use transform=\"translate(58.398438 0.015625)\" xlink:href=\"#DejaVuSans-Oblique-105\"/>\n",
       "     <use transform=\"translate(86.181641 0.015625)\" xlink:href=\"#DejaVuSans-Oblique-110\"/>\n",
       "     <use transform=\"translate(149.560547 0.015625)\" xlink:href=\"#DejaVuSans-Oblique-116\"/>\n",
       "     <use transform=\"translate(188.769531 0.015625)\" xlink:href=\"#DejaVuSans-54\"/>\n",
       "     <use transform=\"translate(252.392578 0.015625)\" xlink:href=\"#DejaVuSans-52\"/>\n",
       "     <use transform=\"translate(316.015625 0.015625)\" xlink:href=\"#ArialMT-62\"/>\n",
       "    </g>\n",
       "   </g>\n",
       "  </g>\n",
       " </g>\n",
       " <defs>\n",
       "  <clipPath id=\"pf8405f6392\">\n",
       "   <rect height=\"41.491069\" width=\"310.3038\" x=\"0\" y=\"4.504646\"/>\n",
       "  </clipPath>\n",
       " </defs>\n",
       "</svg>"
      ],
      "text/plain": [
       "<IPython.core.display.SVG object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "ename": "RuntimeError",
     "evalue": "1D tensors expected, but got 2D and 2D tensors\nCause: torch.dot(b,b) tensor arg b w/shape [2, 1], arg b w/shape [2, 1]",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "\u001b[0;32m/var/folders/93/9kzk2ccm8xj8k70059b28jk80000gp/T/ipykernel_55352/2660314622.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     12\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     13\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mtsensor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclarify\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m     \u001b[0mW\u001b[0m \u001b[0;34m@\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m+\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0meye\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m@\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mz\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     15\u001b[0m \u001b[0;31m# W[33, 33] = 3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     16\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mabs\u001b[0m\u001b[0;34m(\u001b[0m \u001b[0mW\u001b[0m \u001b[0;34m@\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mRuntimeError\u001b[0m: 1D tensors expected, but got 2D and 2D tensors\nCause: torch.dot(b,b) tensor arg b w/shape [2, 1], arg b w/shape [2, 1]"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import tsensor\n",
    "import sys\n",
    "\n",
    "W = torch.tensor([[1, 2], [3, 4]])\n",
    "b = torch.tensor([9, 10]).reshape(2, 1)\n",
    "x = torch.tensor([4, 5]).reshape(2, 1)\n",
    "h = torch.tensor([1,2])\n",
    "# z + z + W @ z\n",
    "# W @ z\n",
    "#torch.dot(b, 3)\n",
    "\n",
    "with tsensor.clarify():\n",
    "    W @ torch.dot(b,b)+ torch.eye(2,2)@x + z\n",
    "# W[33, 33] = 3\n",
    "b = torch.abs( W @ b + x )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "1D tensors expected, got 2D, 2D tensors at /tmp/pip-req-build-as628lz5/aten/src/TH/generic/THTensorEvenMoreMath.cpp:83\nCause: torch.dot(b,b) tensor arg b w/shape [2, 1], arg b w/shape [2, 1]",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-4-fd44e2c68a52>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mtsensor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclarify\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0mW\u001b[0m \u001b[0;34m@\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m+\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0meye\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m@\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mz\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mRuntimeError\u001b[0m: 1D tensors expected, got 2D, 2D tensors at /tmp/pip-req-build-as628lz5/aten/src/TH/generic/THTensorEvenMoreMath.cpp:83\nCause: torch.dot(b,b) tensor arg b w/shape [2, 1], arg b w/shape [2, 1]"
     ]
    }
   ],
   "source": [
    "with tsensor.clarify():\n",
    "    W @ torch.dot(b,b)+ torch.eye(2,2)@x + z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Graphviz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<NAME:b>, <EQUAL:=>, <NAME:W>, <AT:@>, <NAME:h>, <PLUS:+>, <NAME:torch>, <DOT:.>, <NAME:abs>, <LPAR:(>, <NAME:x>, <RPAR:)>, <STAR:*>, <NAME:h>, <DOT:.>, <NAME:dot>, <LPAR:(>, <NAME:h>, <RPAR:)>, <ENDMARKER:>]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Assign(lhs=b,rhs=BinaryOp(op=<PLUS:+>,lhs=BinaryOp(op=<AT:@>,lhs=W,rhs=h),rhs=BinaryOp(op=<STAR:*>,lhs=Call(func=Member(obj=torch,member=abs),args=[x]),rhs=Call(func=Member(obj=h,member=dot),args=[h]))))"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p = tsensor.parse.PyExprParser(\"b = W @ h + torch.abs(x) *h.dot(h)\")\n",
    "print(p.tokens)\n",
    "root = p.parse()\n",
    "root"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[25, 31],\n",
       "        [30, 36]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "frame = sys._getframe()\n",
    "result = root.eval(frame)\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def postorder(t):\n",
    "    nodes = []\n",
    "    _postorder(t, nodes)\n",
    "    return nodes\n",
    "def _postorder(t, nodes):\n",
    "    if t is None:\n",
    "        return\n",
    "    for sub in t.kids:\n",
    "        _postorder(sub, nodes)\n",
    "    nodes.append(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def leaves(t):\n",
    "    nodes = []\n",
    "    _leaves(t, nodes)\n",
    "    return nodes\n",
    "def _leaves(t, nodes):\n",
    "    if t is None:\n",
    "        return\n",
    "    if len(t.kids)==0:\n",
    "        nodes.append(t)\n",
    "        return\n",
    "    for sub in t.kids:\n",
    "        _leaves(sub, nodes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "nodes = postorder(root)\n",
    "atoms = leaves(root)\n",
    "atoms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# map tokens to nodes\n",
    "tok2node = {}\n",
    "for nd in atoms:\n",
    "    tok2node[nd.token] = nd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def walk(t, pre=lambda x:None, post=lambda x:None):\n",
    "    if t is None:\n",
    "        return\n",
    "    pre(t)\n",
    "    for sub in t.kids:\n",
    "        walk(sub, pre, post)\n",
    "    post(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import graphviz\n",
    "\n",
    "s = \"\"\"\n",
    "digraph G {\n",
    "    nodesep=.1;\n",
    "    ranksep=.3;\n",
    "    rankdir=BT;\n",
    "    ordering=out; # keep order of leaves\n",
    "    node [penwidth=\"0.5\", shape=plaintext, width=.1, height=.1];\n",
    "\"\"\"\n",
    "\n",
    "nodesS = set(nodes)\n",
    "atomsS = set(atoms)\n",
    "ops = nodesS.difference(atomsS)\n",
    "\n",
    "# s += f'{{ rank=same;'\n",
    "# for a in atoms:\n",
    "#     s += f' node{id(tok2node[a.token])};'\n",
    "# s += '}\\n'\n",
    "\n",
    "s += f'{{ rank=same;'\n",
    "for t in p.tokens:\n",
    "    if t.type!=tsensor.ENDMARKER:\n",
    "        x = tok2node[t] if t in tok2node else t\n",
    "        shape = \"\"\n",
    "        sh = tsensor._shape(x.value)\n",
    "        if x in atomsS and sh is not None:\n",
    "            shape = \"shape=box, fixedsize=shape \"\n",
    "            if len(sh)==1:\n",
    "                shape += f\"width={.15}, height={sh[0]/6.66}\"\n",
    "            elif len(sh)==2:\n",
    "                shape += f\"width={sh[1]/6.66}, height={sh[0]/6.66}\"\n",
    "#         print(sh, shape)\n",
    "        s += f'leaf{id(x)} [{shape} label=<<font face=\"Consolas\" color=\"#444443\" point-size=\"9\">{t.value}</font>>]\\n'\n",
    "s += '}\\n'\n",
    "\n",
    "# for nd in ops:\n",
    "#     s += f'leaf{id(nd)} [label=<<font face=\"Consolas\" color=\"#444443\" point-size=\"9\">{str(nd)}</font>>]'\n",
    "\n",
    "for nd in nodes:\n",
    "    if nd in ops:\n",
    "        text = str(nd)\n",
    "#         if isinstance(nd, tsensor.Atom):\n",
    "#             text = str(nd)\n",
    "#         else:\n",
    "#             text = nd.__class__.__name__\n",
    "#         text = str(nd)#+\"\\n\"+str(nd.value)\n",
    "#         text = \" \"\n",
    "        shape = \"\"\n",
    "        sh = tsensor._shape(nd.value)\n",
    "        if sh is not None:\n",
    "            shape = \"shape=box, fixedsize=shape \"\n",
    "            if len(sh)==1:\n",
    "                shape += f\"width={.15}, height={sh[0]/6.66}\"\n",
    "            elif len(sh)==2:\n",
    "                shape += f\"width={sh[1]/6.66}, height={sh[0]/6.66}\"\n",
    "        if sh is not None:\n",
    "            text += \"<br/>\"+'x'.join(str(s) for s in sh)\n",
    "#         else:\n",
    "#             text += \"=\"+str(nd.value)\n",
    "        s += f'node{id(nd)} [{shape} label=<<font face=\"Consolas\" color=\"#444443\" point-size=\"9\">{text}</font>>]\\n'\n",
    "\n",
    "# link leaves left to right\n",
    "for i in range(len(p.tokens)-2):\n",
    "    t = p.tokens[i]\n",
    "    t2 = p.tokens[i+1]\n",
    "    x = tok2node[t] if t in tok2node else t\n",
    "    x2 = tok2node[t2] if t2 in tok2node else t2\n",
    "    s += f'leaf{id(x)} -> leaf{id(x2)} [style=invis];\\n'\n",
    "    \n",
    "for nd in nodes:\n",
    "    kids = nd.kids\n",
    "#     if isinstance(nd, tsensor.Call) and isinstance(nd.kids[0], tsensor.Member):\n",
    "#         print('ignore', nd)\n",
    "#         kids = kids[1:]\n",
    "    for sub in kids:\n",
    "        if sub in atomsS:\n",
    "            s += f'node{id(nd)} -> leaf{id(sub)} [dir=back, penwidth=\"0.5\", color=\"#444443\", arrowsize=.4];\\n'\n",
    "        else:\n",
    "            s += f'node{id(nd)} -> node{id(sub)} [dir=back, penwidth=\"0.5\", color=\"#444443\", arrowsize=.4];\\n'\n",
    "s += \"}\\n\"\n",
    "graphviz.Source(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import graphviz\n",
    "\n",
    "s = \"\"\"\n",
    "digraph G {\n",
    "    nodesep=.1;\n",
    "    ranksep=.3;\n",
    "    rankdir=BT;\n",
    "    ordering=out; # keep order of leaves\n",
    "    node [penwidth=\"0.5\", shape=plaintext, width=.1, height=.1];\n",
    "\"\"\"\n",
    "\n",
    "nodesS = set(nodes)\n",
    "atomsS = set(atoms)\n",
    "ops = nodesS.difference(atomsS)\n",
    "\n",
    "s += f'{{ rank=same;'\n",
    "for a in atoms:\n",
    "    s += f'node{id(a)};'\n",
    "s += '}\\n'\n",
    "\n",
    "for nd in nodes:\n",
    "    if isinstance(nd, tsensor.Atom):\n",
    "        text = str(nd)\n",
    "    else:\n",
    "        text = nd.__class__.__name__\n",
    "    shape = \"\"\n",
    "    sh = _shape(nd.value)\n",
    "    if sh is not None:\n",
    "        shape = \"shape=box, fixedsize=shape \"\n",
    "        if len(sh)==1:\n",
    "            shape += f\"width={.15}, height={sh[0]/6.66}\"\n",
    "        elif len(sh)==2:\n",
    "            shape += f\"width={sh[1]/6.66}, height={sh[0]/6.66}\"\n",
    "    s += f'node{id(nd)} [{shape} label=<<font face=\"Consolas\" color=\"#444443\" point-size=\"9\">{text}</font>>]\\n'\n",
    "    \n",
    "for nd in nodes:\n",
    "    kids = nd.kids\n",
    "#     if isinstance(nd, tsensor.Call) and isinstance(nd.kids[0], tsensor.Member):\n",
    "#         print('ignore', nd)\n",
    "#         kids = kids[1:]\n",
    "    for sub in kids:\n",
    "        if sub in atomsS:\n",
    "            s += f'node{id(nd)} -> node{id(sub)} [dir=back, penwidth=\"0.5\", color=\"#444443\", arrowsize=.4];'\n",
    "        else:\n",
    "            s += f'node{id(nd)} -> node{id(sub)} [dir=back, penwidth=\"0.5\", color=\"#444443\", arrowsize=.4];'\n",
    "s += \"}\\n\"\n",
    "graphviz.Source(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "W = torch.tensor([[1, 2], [3, 4], [5, 6]])\n",
    "b = torch.tensor([9, 10]).reshape(2, 1)\n",
    "x = torch.tensor([4, 5]).reshape(2, 1)\n",
    "h = torch.tensor([1,2])\n",
    "a = 3\n",
    "\n",
    "x = torch.tensor([4, 5]).reshape(2, 1)\n",
    "p = tsensor.PyExprParser(\"a = a\")\n",
    "p = tsensor.PyExprParser(\"b = W@b + torch.abs(x) + h.dot(h)\")\n",
    "p = tsensor.PyExprParser(\"b = W@b + h.dot(h)\")\n",
    "print(p.tokens)\n",
    "root = p.parse()\n",
    "nodes = postorder(root)\n",
    "atoms = leaves(root)\n",
    "# map tokens to nodes\n",
    "tok2node = {}\n",
    "for nd in atoms:\n",
    "    tok2node[nd.token] = nd\n",
    "frame = sys._getframe()\n",
    "result = root.eval(frame)\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import graphviz\n",
    "\n",
    "def matrix_html(nrows, ncols, label, fontsize=12, fontname=\"Consolas\", dimfontsize=9, color=\"#cfe2d4\"):\n",
    "    isvec = ncols==None\n",
    "    if isvec:\n",
    "        sz = str(nrows)\n",
    "        ncols=nrows\n",
    "        nrows=1\n",
    "    else:\n",
    "        sz = f\"{nrows}x{ncols}\"\n",
    "    w = ncols*20\n",
    "    h = nrows*20\n",
    "    if ncols==1:\n",
    "        w = 15\n",
    "    if nrows==1:\n",
    "        h = 15\n",
    "    html = f\"\"\"\n",
    "    <table fixedsize=\"true\" width=\"{w}\" height=\"{h+2*fontsize*1.3}\" BORDER=\"0\" CELLPADDING=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n",
    "    <tr>\n",
    "    <td fixedsize=\"true\" width=\"{w}\" height=\"{fontsize*1.3}\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" valign=\"top\" align=\"center\">\n",
    "    <font face=\"{fontname}\" color=\"#444443\" point-size=\"{dimfontsize}\">{sz}</font>\n",
    "    </td>\n",
    "    </tr>\n",
    "    <tr>    \n",
    "    <td fixedsize=\"true\" width=\"{w}\" height=\"{h}\" cellspacing=\"0\" cellpadding=\"0\" bgcolor=\"{color}\" border=\"1\" sides=\"ltbr\" align=\"center\">\n",
    "    <font face=\"{fontname}\" color=\"#444443\" point-size=\"{fontsize}\">{label}</font>\n",
    "    </td>\n",
    "    </tr>\n",
    "    </table>\"\"\"\n",
    "    return html\n",
    "\n",
    "nodesS = set(nodes)\n",
    "atomsS = set(atoms)\n",
    "ops = nodesS.difference(atomsS)\n",
    "\n",
    "s = \"\"\"\n",
    "digraph G {\n",
    "    nodesep=.0;\n",
    "    ranksep=.3;\n",
    "    rankdir=BT;\n",
    "    ordering=out; # keep order of leaves\n",
    "\"\"\"\n",
    "\n",
    "fontname=\"Consolas\"\n",
    "fontsize=12\n",
    "spread = .2\n",
    "\n",
    "s += f'{{ rank=same; '\n",
    "for t in p.tokens:\n",
    "    if t.type!=tsensor.ENDMARKER:\n",
    "        x = tok2node[t] if t in tok2node else t\n",
    "        shape = \"\"\n",
    "        sh = tsensor._shape(x.value)\n",
    "        label = f'<font face=\"{fontname}\" color=\"#444443\" point-size=\"{fontsize}\">{t.value}</font>'\n",
    "        matrixcolor=\"#cfe2d4\"\n",
    "        vectorcolor=\"#fefecd\"\n",
    "        if x in atomsS and sh is not None:\n",
    "            if len(sh)==1:\n",
    "                label = matrix_html(sh[0],None,t.value,fontname=fontname,fontsize=fontsize,color=vectorcolor)\n",
    "            elif len(sh)==2:\n",
    "                label = matrix_html(sh[0],sh[1],t.value,fontname=fontname,fontsize=fontsize,color=matrixcolor)\n",
    "        # margin/width don't seem to do anything for shape=plain\n",
    "        if t.type==tsensor.DOT:\n",
    "            spread=.1\n",
    "        if t.type==tsensor.EQUAL:\n",
    "            spread=.25\n",
    "        if t.type in tsensor.ADDOP:\n",
    "            spread=.5\n",
    "        if t.type in tsensor.MULOP:\n",
    "            spread=.2\n",
    "        s += f'leaf{id(x)} [shape=box penwidth=0 margin=.001 width={spread} label=<{label}>]\\n'\n",
    "s += '}\\n'\n",
    "\n",
    "s += \"}\\n\"\n",
    "# print(s)\n",
    "graphviz.Source(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = \"\"\"\n",
    "digraph foo {\n",
    "    rankdir=TB\n",
    "    subgraph {\n",
    "        node1;\n",
    "    }\n",
    "    subgraph {\n",
    "        node2;\n",
    "    }\n",
    "    node1 -> node2\n",
    "}\n",
    "\"\"\"\n",
    "display(graphviz.Source(s))\n",
    "display(graphviz.Source(s))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get string size in matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib\n",
    "import matplotlib.patches as patches\n",
    "from matplotlib import pyplot as plt\n",
    "def textdim(s, fontsize=11):\n",
    "    fig, ax = plt.subplots(1,1)\n",
    "    t = ax.text(0, 0, s, bbox={'lw':0}, fontsize=fontsize)\n",
    "    plt.savefig(\"/tmp/junk\")\n",
    "    plt.close()\n",
    "    bb = t.get_bbox_patch()\n",
    "    w, h = bb.get_width(), bb.get_height()\n",
    "    return w, h"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "textdim(\"test of foO\", fontsize=11)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "a = [[1,2,3],[3,4,5]]\n",
    "objviz(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from lolviz import *\n",
    "print(objviz(a).source)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = \"\"\"\n",
    "digraph G {\n",
    "    ranksep=0;\n",
    "    rankdir=BT;\n",
    "    ordering=out; # keep order of leaves\n",
    "    node1 [shape=plain, space=\"0.0\", margin=\"0.01\",label=<\n",
    "<table BORDER=\"0\" CELLPADDING=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n",
    "<tr>\n",
    "<td  width=\"100\" height=\"12\" cellspacing=\"0\" cellpadding=\"0\" border=\"1\" sides=\"b\" valign=\"top\" align=\"center\">100x200</td>\n",
    "</tr>\n",
    "<tr>\n",
    "<td  width=\"100\" height=\"88\" cellspacing=\"0\" cellpadding=\"0\" border=\"1\" sides=\"lbr\" align=\"center\">self.W</td>\n",
    "</tr>\n",
    "</table>\n",
    "    >]\n",
    "}\n",
    "\"\"\"\n",
    "graphviz.Source(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CSS (yuck)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.core.display import display, HTML\n",
    "h = \"\"\"\n",
    "<h6 style=\"color: Green; position:absolute; top: 20vh; left: 25vw; height: auto; margin: auto;\">Actief</h6>\n",
    "<table>\n",
    "<tr>\n",
    "    <td>b = torch.abs( W @ b +</td>\n",
    "    <td><div style=\"width:100px;height:150px;border:1px solid #000;\">\n",
    "    <table style=\"width:100px;height:150px\" border='0' cellborder='0' cellpadding=\"0\" cellspacing=\"0\">\n",
    "           <tr>\n",
    "               <td height=\"50%\" width=\"33%\"></td>\n",
    "               <td width=\"33%\" cellpadding=\"0\" cellspacing=\"0\" align=center valign=top>40</td><td width=\"33%\"></td>\n",
    "           </tr>\n",
    "           <tr>\n",
    "               <td width=\"33%\" cellpadding=\"0\" cellspacing=\"0\">100</td>\n",
    "               <td width=\"33%\" cellpadding=\"0\" cellspacing=\"0\" align=\"center\">self.W</td>\n",
    "               <td width=\"33%\"></td>\n",
    "           </tr>\n",
    "         </table>\n",
    "    </div>\n",
    "    </td>\n",
    "    <td>)</td>\n",
    "</tr>\n",
    "\"\"\"\n",
    "t = HTML(h)\n",
    "t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def matrix(nrows,ncols,text,dim_fontsize=9,fontsize=12):\n",
    "    h = f\"\"\"\n",
    "    <div style=\"position:relative; width:{ncols}px;height:{nrows*1.2}px; padding:0px\">\n",
    "     <div style=\"position:relative; width:{ncols}px;height:{nrows}px;border:1px solid #000; padding:0px\">\n",
    "      <div style=\"position:absolute; width:{ncols}px; top: -3px; text-align:center; font-size:{dim_fontsize}px\">\n",
    "        {ncols}\n",
    "      </div>\n",
    "      <div style=\"position:absolute; top: 40%; left: -3px; transform: rotate(-90deg); font-size:{dim_fontsize}px\">\n",
    "        {nrows}\n",
    "      </div>\n",
    "     </div>\n",
    "     <div style=\"position:absolute; width:{ncols}px; bottom: 5px; text-align:center; font-size:{fontsize}px\">\n",
    "        {text}\n",
    "     </div>\n",
    "    </div>\n",
    "    \"\"\"\n",
    "    sp = f\"\"\"\n",
    "    <div style=\"position:relative; width:{ncols}px;height:{nrows*1.2}px; padding:0px\">\n",
    "     <span style=\"position:relative; width:{ncols}px;height:{nrows}px;border:1px solid #000; padding:0px\">\n",
    "      <span style=\"position:absolute; width:{ncols}px; top: -3px; text-align:center; font-size:{dim_fontsize}px\">\n",
    "        {ncols}\n",
    "      </span>\n",
    "      <span style=\"position:absolute; top: 40%; left: -3px; transform: rotate(-90deg); font-size:{dim_fontsize}px\">\n",
    "        {nrows}\n",
    "      </span>\n",
    "     </span>\n",
    "     <span style=\"position:absolute; width:{ncols}px; bottom: 5px; text-align:center; font-size:{fontsize}px\">\n",
    "        {text}\n",
    "     </span>\n",
    "    </div>\n",
    "    \"\"\"\n",
    "\n",
    "    return sp\n",
    "\n",
    "m = matrix(120,20,\"self.W\")\n",
    "m = f\"torch.relu({m})\"\n",
    "HTML(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
